package com.itheima.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.itheima.constant.RedisConstant;
import com.itheima.dao.CheckGroupDao;
import com.itheima.dao.CheckItemDao;
import com.itheima.dao.SetmealDao;
import com.itheima.entity.PageResult;
import com.itheima.entity.QueryPageBean;
import com.itheima.pojo.CheckGroup;
import com.itheima.pojo.CheckItem;
import com.itheima.pojo.Setmeal;
import com.itheima.service.SetmealService;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service(interfaceClass = SetmealService.class)
@Transactional
public class SetmealServiceImpl implements SetmealService {
    @Autowired
    private SetmealDao setmealDao;
    @Autowired
    private JedisPool jedisPool;
    @Autowired
    private CheckGroupDao checkGroupDao;
    @Autowired
    private CheckItemDao checkItemDao;
    @Autowired
    private FreeMarkerConfigurer freeMarkerConfigurer;
    @Value("${out_put_path}")
    private String outputpath;

    /**
     * 分页查询
     *
     * @param queryPageBean
     * @return
     */
    @Override
    public PageResult findPage(QueryPageBean queryPageBean) {
        //分页参数传递给分页助手处理
        PageHelper.startPage(queryPageBean.getCurrentPage(), queryPageBean.getPageSize());
        //通过条件查询
        Page<Setmeal> page = setmealDao.findByCondition(queryPageBean.getQueryString());
        //返回结果
        return new PageResult(page.getTotal(), page.getResult());
    }

    /**
     * 新增套餐
     *
     * @param setmeal
     * @param checkgroupIds
     */
    @Override
    public void save(Setmeal setmeal, Integer[] checkgroupIds) {
        //添加套餐
        setmealDao.save(setmeal);
        //设置套餐与检查项的关联关系
        setSetmealAndCheckGroup(setmeal.getId(), checkgroupIds);
        //将图片名称保存到Redis，套餐图片保存在数据库中的图片名称
        Jedis resource = jedisPool.getResource();
        resource.sadd(RedisConstant.SETMEAL_PIC_DB_RESOURCES, setmeal.getImg());

        //新增套餐后需要重新生成静态页面
        generateMobileStaticHtml();

        //归还资源
        resource.close();
    }

    //生成静态页面
    public void generateMobileStaticHtml() {
        //准备模板文件中所需的数据
        List<Setmeal> setmealList = this.getAllSetmeal();
        //需要生成套餐列表静态页面
        generateMobileSetmealListHtml(setmealList);
        //需要生成套餐详情静态页面
        generateMobileSetmealDetailHtml(setmealList);

    }

    //生成套餐列表静态页面
    public void generateMobileSetmealListHtml(List<Setmeal> setmealList) {
        //创建map集合保存套餐集合信息
        Map map = new HashMap<>();
        map.put("setmealList", setmealList);
        //将参数传递，生成套餐列表静态页面
        generteHtml("mobile_setmeal.ftl", "m_setmeal.html", map);
    }

    //生成套餐详情静态页面
    public void generateMobileSetmealDetailHtml(List<Setmeal> setmealList) {
        //遍历集合
        for (Setmeal setmeal : setmealList) {
            //创建map集合保存套餐集合信息
            Map map = new HashMap<>();
            map.put("setmeal", setmealDao.findBySetmealId(setmeal.getId()));
            //将参数传递，生成套餐详情静态页面
            generteHtml("mobile_setmeal_detail.ftl", "setmeal_detail_" + setmeal.getId() + ".html", map);
        }
    }

    /**
     * 通用的方法，用于生成静态页面
     *
     * @param templateName 模板名称
     * @param htmlPageName 静态页面名称
     * @param map          保存数据的容器
     */
    public void generteHtml(String templateName, String htmlPageName, Map map) {
        //获取配置对象
        Configuration configuration = freeMarkerConfigurer.getConfiguration();
        Writer out = null;
        try {
            //获取模板对象
            Template template = configuration.getTemplate(templateName);
            //构造输出流对象
            out = new FileWriter(new File(outputpath + htmlPageName));
            //输出文件
            template.process(map, out);
            //关流
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置套餐与检查项的关联关系
     *
     * @param setmealId
     * @param checkgroupIds
     */
    private void setSetmealAndCheckGroup(Integer setmealId, Integer[] checkgroupIds) {
        //判断检查项是否为空
        if (checkgroupIds != null && checkgroupIds.length > 0) {
            //遍历
            for (Integer checkgroupId : checkgroupIds) {
                //创建集合保存关联关系
                Map<String, Integer> map = new HashMap<>();
                map.put("setmealId", setmealId);
                map.put("checkgroupId", checkgroupId);
                setmealDao.setSetmealAndCheckGroup(map);
            }
        }
    }

    /**
     * 根据id查询套餐
     *
     * @param setmealId
     * @return
     */
    @Override
    public Setmeal findById(Integer setmealId) {
        return setmealDao.findById(setmealId);
    }

    /**
     * 根据套餐id查询检查组
     *
     * @param setmealId
     * @return
     */
    @Override
    public Integer[] findCheckgroupIdsBysetmealId(Integer setmealId) {
        return setmealDao.findCheckgroupIdsBysetmealId(setmealId);
    }

    /**
     * 编辑套餐信息
     *
     * @param setmeal
     * @param checkgroupIds
     */
    @Override
    public void update(Setmeal setmeal, Integer[] checkgroupIds) {
        //根据套餐id先清空套餐与检查项的关联数据
        setmealDao.deleteBysetmealId(setmeal.getId());
        //在设置套餐和检查项的关联关系
        setSetmealAndCheckGroup(setmeal.getId(), checkgroupIds);
        //通过id获取原套餐
        Setmeal oldSetmeal = setmealDao.findById(setmeal.getId());
        //判断是否重新上传图片
        if (!oldSetmeal.getImg().equals(setmeal.getImg())) {
            Jedis resource = jedisPool.getResource();
            //如果不相等，则删除redis原套餐图片信息
            resource.srem(RedisConstant.SETMEAL_PIC_DB_RESOURCES, oldSetmeal.getImg());
            //更新套餐信息
            setmealDao.update(setmeal);
            //将新图片名称信息保存到Redis中
            resource.sadd(RedisConstant.SETMEAL_PIC_DB_RESOURCES, setmeal.getImg());

            //修改套餐后需要重新生成静态页面
            generateMobileStaticHtml();

            //归还资源
            resource.close();
        } else {
            //如果相等，说明图片没有重新上传，直接更新套餐信息
            setmealDao.update(setmeal);

            //修改套餐后需要重新生成静态页面
            generateMobileStaticHtml();
        }
    }

    /**
     * 删除套餐
     *
     * @param setmealId
     */
    @Override
    public void deleteById(Integer setmealId) {
        //先根据套餐id查询检查组
        Integer[] ids = findCheckgroupIdsBysetmealId(setmealId);
        //如果存在关联关系
        if (ids != null && ids.length > 0) {
            //先删除关联关系
            setmealDao.deleteBysetmealId(setmealId);
        }
        //通过id获取套餐
        Setmeal setmeal = setmealDao.findById(setmealId);
        Jedis resource = jedisPool.getResource();
        //删除redis套餐图片信息
        resource.srem(RedisConstant.SETMEAL_PIC_DB_RESOURCES, setmeal.getImg());
        //归还资源
        resource.close();
        //删除套餐
        setmealDao.deleteById(setmealId);

        //删除套餐后需要重新生成静态页面
        generateMobileStaticHtml();
    }

    /**
     * 查询所有套餐信息
     *
     * @return
     */
    @Override
    public List<Setmeal> getAllSetmeal() {
        return setmealDao.getAllSetmeal();
    }

    /**
     * 根据套餐ID查询套餐详细信息（包括套餐基本信息、套餐包含的检查组、检查组包含的检查项）
     *
     * @param setmealId
     * @return
     */
    @Override
    /*public Setmeal findBySetmealId(Integer setmealId) {
        return setmealDao.findBySetmealId(setmealId);
    }*/
    public Setmeal findBySetmealId(Integer setmealId) {
        Setmeal setmeal = setmealDao.findSetmealById(setmealId);
        //根据套餐id查询检查组
        List<CheckGroup> checkGroupList = checkGroupDao.findBySetmealId(setmealId);
        //遍历检查组
        for (CheckGroup checkGroup : checkGroupList) {
            //根据检查组id查询检查项
            List<CheckItem> checkItemList = checkItemDao.findCheckItemById(checkGroup.getId());
            //将检查项封装到检查组中
            checkGroup.setCheckItems(checkItemList);
        }
        //将检查组封装到套餐中
        setmeal.setCheckGroups(checkGroupList);
        //返回套餐结果
        return setmeal;
    }

    /**
     * 统计套餐预约情况
     *
     * @return
     */
    @Override
    public List<Map<String, Object>> findSetmealCount() {
        return setmealDao.findSetmealCount();
    }


    //套餐收入统计
    @Override
    public Map<String, Object> findSetmealIncome(String startTime,String endTime) {
        Map<String,Object>map=new HashMap<>();
        //调用dao层获取每个套餐的收入
        List<Map<String,Object>> setMealIncome=setmealDao.findSetmealIncomeCount(startTime, endTime);
        //调用dao层获取总收入
        Integer totalIncome= setmealDao.totalIncome(startTime,endTime);
        //创建map集合封装总收入
        Map<String,Object> map2=new HashMap<>();
        map2.put("value",totalIncome);//总收入的值
        map2.put("name","总收入");//总收入名字
        setMealIncome.add(map2);//将总收入相关信息封装到list中
        map.put("setMealIncome",setMealIncome);

        //套餐名字集合
        List<String> setMealNames=new ArrayList<>();
        for (Map<String, Object> smap : setMealIncome) {
            String name = (String) smap.get("name");
            setMealNames.add(name);
        }
        map.put("setMealNames",setMealNames);
        //  System.out.println(map);
        return map;

    }


    //套餐收入统计（默认页面）
    @Override
    public Map<String, Object> findSetmealIncome() {
        Map<String,Object>map=new HashMap<>();
        //调用dao层获取每个套餐的收入
        List<Map<String,Object>> setMealIncome=setmealDao.findSetmealIncomeCount1();
        //调用dao层获取总收入
        Integer totalIncome= setmealDao.totalIncome1();
        //创建map集合封装总收入
        Map<String,Object> map2=new HashMap<>();
        map2.put("value",totalIncome);//总收入的值
        map2.put("name","总收入");//总收入名字
        setMealIncome.add(map2);//将总收入相关信息封装到list中
        map.put("setMealIncome",setMealIncome);

        //套餐名字集合
        List<String> setMealNames=new ArrayList<>();
        for (Map<String, Object> smap : setMealIncome) {
            String name = (String) smap.get("name");
            setMealNames.add(name);
        }
        map.put("setMealNames",setMealNames);
        //  System.out.println(map);
        return map;

    }

}
